﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Mt.Site.Application.Dto;
using Mt.Site.Application.Dto.ManualSynchorize;
using Mt.Site.Core.Navigations.Entities;
using Mt.Site.Core.Navigations.MenuInfo;
using Mt.Site.Core.Navigations.Permissions;
using Mt.Site.Core.Navigations.Values;
using Mt.Site.Core.Synchronization;
using Mt.Site.Core.Synchronization.Data;
using Mt.Site.Core.Synchronization.Navigations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Mt.Site.Application.Navigation
{
    public class MenuInfoSyncAppService : MtSiteAppServiceBase, IMenuInfoSyncAppService
    {
        private readonly IMenuInfoManualSyncManager _menuInfoManualSyncManager;

        private readonly IRepository<ChannelObject, Guid> _channelObjectRepository;
        private readonly IRepository<MenuConfig, Guid> _menuConfigRepository;

        private readonly ISynchronizationHelper _synchronizationHelper;

        public MenuInfoSyncAppService(
            IMenuInfoManualSyncManager menuInfoManualSyncManager,
            IRepository<ChannelObject, Guid> channelObjectRepository,
            IRepository<MenuConfig, Guid> menuConfigRepository,
            ISynchronizationHelper synchronizationHelper)
        {
            _menuInfoManualSyncManager = menuInfoManualSyncManager;
            _channelObjectRepository = channelObjectRepository;
            _menuConfigRepository = menuConfigRepository;
            _synchronizationHelper = synchronizationHelper;
        }

        #region Config

        [AbpAuthorize(MenuPermissions.Pages_Tenant_MenusInfo_Config_Edit)]
        public async Task<ManualSyncOut> SyncMenuConfigAsync(MenuIdDto input)
        {
            return await SyncConfigAsync(input, MenuInfoManager.Config);
        }

        [AbpAuthorize(MenuPermissions.Pages_Tenant_MenusInfo_Config_Edit)]
        public async Task<ManualSyncOut> SyncCustomConfigAsync(MenuIdDto input)
        {
            return await SyncConfigAsync(input,MenuInfoManager.CustomedConfig);
        }

        [AbpAuthorize(MenuPermissions.Pages_Tenant_MenusInfo_CustomData_Edit)]
        public async Task<ManualSyncOut> SyncCustomDataAsync(MenuIdDto input)
        {
            return await SyncConfigAsync(input, MenuInfoManager.CustomedData);
        }

        private async Task<ManualSyncOut> SyncConfigAsync(MenuIdDto input,string type)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var motherSiteInfo = _synchronizationHelper.GetMotherSiteInfo(AbpSession.GetTenantId(), AbpSession.CultureName());

                if (motherSiteInfo == null)
                {
                    throw new UserFriendlyException(L("NoMotherSite"));
                }

                var motherEntity = await _menuConfigRepository.FirstOrDefaultAsync(
                    item => item.TenantId == motherSiteInfo.MotherTenantId && item.MenuId == input.MenuId && item.Type == type);
                if (motherEntity == null)
                {
                    throw new UserFriendlyException(L("NoSourceDataInMotherSite"));
                }
                var toId = _menuInfoManualSyncManager.CreateOrUpdateConfigManualSync(
                        new CreateOrUpdateSynchorizeStore
                        {
                            ToTenantId = AbpSession.GetTenantId(),
                            Id = motherEntity.Id,
                            TargetLanguage = AbpSession.CultureName()
                        });

                if (toId != Guid.Empty)
                {
                    return new ManualSyncOut
                    {
                        SyncResult = true
                    };
                }
            }
            return new ManualSyncOut
            {
                SyncResult = false
            };
        }

        #endregion

        #region 扩展数据

        [AbpAuthorize(MenuPermissions.Pages_Tenant_MenusInfo_ExtendedData_Edit)]
        public ManualSyncOut SetExtendedData(ManualSyncInput input)
        {              
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var motherSiteInfo = _synchronizationHelper.GetMotherSiteInfo(AbpSession.GetTenantId(), AbpSession.CultureName());
                if (motherSiteInfo == null)
                {
                    throw new UserFriendlyException(L("NoMotherSite"));
                }

                var menuAuxiliaryId = _synchronizationHelper.GetAuxiliaryIdForMenuItem(input.Id);
                var menuId = _synchronizationHelper.GetMenuId(menuAuxiliaryId, motherSiteInfo.MotherTenantId);
                if (menuId == Guid.Empty)
                {
                    throw new UserFriendlyException(L("NoSourceDataInMotherSite"));
                }

                var motherEntity = _channelObjectRepository.FirstOrDefault(
                        item => item.MenuId == menuId && item.Key == MenuExtendedData.Key
                        && item.Language == motherSiteInfo.MotherLanguage && item.TenantId == motherSiteInfo.MotherTenantId);
                if (motherEntity == null)
                {
                    throw new UserFriendlyException(L("NoSourceDataInMotherSite"));
                }

                var toId = _menuInfoManualSyncManager.CreateOrUpdateImgTextSync(
                        new SyncArgs_Guid
                        {
                            ToTenantId = AbpSession.GetTenantId(),
                            Id = motherEntity.Id,
                            TargetLanguage = AbpSession.CultureName(),
                            MenuId = menuAuxiliaryId
                        });

                if (toId != Guid.Empty)
                {
                    return new ManualSyncOut
                    {
                        SyncResult = true
                    };
                }
            }
            return new ManualSyncOut
            {
                SyncResult = false
            };
        }

        #endregion

        #region 图文

        [HttpPost]
        public async Task<PagedResultDto<MotherSiteDataOut>> GetImgTextFromMotherSiteAsync(GetMotherSiteInput input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var motherSiteInfo = _synchronizationHelper.GetMotherSiteInfo(AbpSession.GetTenantId(), AbpSession.CultureName());
                if (motherSiteInfo == null)
                {
                    return null;
                }
                var menuId = _synchronizationHelper.GetMenuId(input.MenuId, motherSiteInfo.MotherTenantId);
                if (menuId == Guid.Empty)
                {
                    return null;
                }

                var query = _channelObjectRepository.GetAll()
                             .Where(item => item.TenantId == motherSiteInfo.MotherTenantId && item.Language == motherSiteInfo.MotherLanguage
                                && item.MenuId == menuId)
                             .WhereIf(!input.Filter.IsNullOrWhiteSpace(), item => item.Title.Contains(input.Filter))
                             .WhereIf(!input.Alias.IsNullOrWhiteSpace(),item=>item.Key == input.Alias);

                query = !input.Sorting.IsNullOrWhiteSpace()
                        ? query.OrderBy(input.Sorting)
                        : query.OrderByDescending(item => item.Order)
                               .ThenByDescending(item => item.CreationTime);
                var count = query.Count();
                var list = await query.ToListAsync();
                var masterDatas = new List<MotherSiteDataOut>();

                foreach (var item in list)
                {
                    masterDatas.Add(new MotherSiteDataOut
                    {
                        Id = item.Id,
                        Title = item.Title,
                        CreationTime = item.CreationTime,
                        LastModificationTime = item.LastModificationTime
                    });
                }
                return new PagedResultDto<MotherSiteDataOut>(count, masterDatas);
            }
        }

        [AbpAuthorize(MenuPermissions.Pages_Tenant_MenusInfo_ImageText_Edit)]
        public ManualSyncOut ManualImgTextSynchorize(ManualSyncInput input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var currentEntity = _channelObjectRepository.FirstOrDefault(input.Id);
                if (currentEntity != null)
                {
                    var menuAuxiliaryId = _synchronizationHelper.GetAuxiliaryIdForMenuItem(currentEntity.MenuId);

                    var toId = _menuInfoManualSyncManager.CreateOrUpdateImgTextSync(
                        new SyncArgs_Guid
                        {
                            Id = input.Id,
                            TargetLanguage = AbpSession.CultureName(),
                            ToTenantId = AbpSession.GetTenantId(),
                            MenuId = menuAuxiliaryId
                        });
                    if (toId != Guid.Empty)
                    {
                        return new ManualSyncOut
                        {
                            SyncResult = true
                        };
                    }
                }
            }
            return new ManualSyncOut
            {
                SyncResult = false
            };
        }

        [AbpAuthorize(MenuPermissions.Pages_Tenant_MenusInfo_ImageText_Edit)]
        public ManualSyncOut ManualImgTextSynchorizeById(ManualSyncTwoInput input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var motherSiteInfo = _synchronizationHelper.GetMotherSiteInfo(AbpSession.GetTenantId(), AbpSession.CultureName());
                if (motherSiteInfo == null)
                {
                    throw new UserFriendlyException(L("NoMotherSite"));
                }

                var currentEntity = _channelObjectRepository.FirstOrDefault(input.Id);
                if (currentEntity == null || currentEntity.SourceID == null || currentEntity.SourceID == Guid.Empty)
                {
                    throw new UserFriendlyException(L("NoSourceDataInMotherSite"));
                }

                var motherEntity = _channelObjectRepository.FirstOrDefault(
                    item => item.Id == currentEntity.SourceID.Value && item.Language == motherSiteInfo.MotherLanguage && item.TenantId == motherSiteInfo.MotherTenantId);
                if (motherEntity == null)
                {
                    throw new UserFriendlyException(L("NoSourceDataInMotherSite"));
                }
                var toId = _menuInfoManualSyncManager.CreateOrUpdateImgTextSync(
                        new SyncArgs_Guid
                        {
                            ToTenantId = AbpSession.GetTenantId(),
                            Id = motherEntity.Id,
                            TargetLanguage = AbpSession.CultureName(),
                            MenuId = input.MenuId
                        });

                if (toId != Guid.Empty)
                {
                    return new ManualSyncOut
                    {
                        SyncResult = true
                    };
                }
            }
            return new ManualSyncOut
            {
                SyncResult = false
            };
        }

        #endregion
    }
}
